import json
from django.http import JsonResponse, HttpResponseBadRequest, HttpResponseNotAllowed
from django.shortcuts import get_object_or_404
from ..users.models import User
from .models import UserDeviceMap
from ..devices.models import Device


def api_response(data=None, message='', code=0, status=200):
    """
    统一返回格式函数。所有 API 响应都使用此格式，便于前端和客户端统一解析。

    Args:
        data (dict|list|None): 响应主体数据，默认为 None
        message (str): 描述信息，如错误原因或成功提示
        code (int): 业务状态码，0 表示成功，非0 表示业务错误
        status (int): HTTP 状态码

    Returns:
        JsonResponse: 包含 code, message, data 的 JSON 响应
    """
    payload = {"code": code, "message": message}
    # 仅当 data 不为 None 时才加入 data 字段，避免返回 null
    if data is not None:
        payload["data"] = data
    # safe=False 允许 data 为 list
    return JsonResponse(payload, status=status, safe=False)


def create_mapping(request):
    """
    创建用户与设备的映射关系。
    Endpoint: POST /api/v1/user-device-map/
    Request Body (JSON): {"user_id": "1", "device_id": 1, "permission": "read"}
    """
    # 仅允许 POST 方法
    if request.method != 'POST':
        return HttpResponseNotAllowed(permitted_methods=['POST'])

    # 解析并校验请求体
    try:
        body = json.loads(request.body)
        user_id = body.get('user_id')  # 获取 user_id
        device_id = body.get('device_id')  # 获取 device_id
        permission = body.get('permission')  # 获取 permission
    except (ValueError, TypeError, json.JSONDecodeError):
        # 解析失败或类型错误，返回 400
        response = api_response(message="请求体格式错误，必须是 JSON", code=1000, status=400)
        return response

    # 检查用户是否存在，不存在则返回业务错误 1001
    try:
        user = User.objects.get(user_id=user_id)
    except User.DoesNotExist:
        response = api_response(message="用户不存在", code=1001, status=404)
        return response

    

    # 检查设备是否存在，不存在则返回业务错误 1002
    try:
        device = Device.objects.get(device_id=device_id)
    except Device.DoesNotExist:
        response = api_response(message="设备不存在", code=1002, status=404)
        return response


    # 防止重复创建映射，若已存在则返回业务错误 1003
    if UserDeviceMap.objects.filter(user=user, device=device).exists():
        response = api_response(message="该映射已存在", code=1003, status=400)
        return response

    # 创建并保存映射
    mapping = UserDeviceMap.objects.create(user=user, device=device, permission=permission)
    data = {
        "user_id": mapping.user.user_id,
        "device_id": mapping.device.device_id,
        "permission": mapping.permission
    }
    return api_response(data=data, message="创建成功", code=0, status=201)


def list_or_filter_mappings(request):
    """
    列出所有映射或根据用户/设备过滤映射。
    Endpoint: GET /api/v1/user-device-map/
    支持可选 query 参数: ?user_id=1 或 ?device_id=2，
    两者都不提供时返回所有映射。
    """
    if request.method != 'GET':
        return HttpResponseNotAllowed(permitted_methods=['GET'])

    user_id = request.GET.get('user_id')      # 用户过滤参数
    device_id = request.GET.get('device_id')  # 设备过滤参数

    qs = UserDeviceMap.objects.all()
    # 如果提供了 user_id，尝试转换并过滤
    if user_id:
        qs = qs.filter(user__user_id=user_id)  
    
    # 按设备ID过滤（保持字符串类型，不转换为整数）
    if device_id:
        qs = qs.filter(device__device_id=device_id)  

    # 构建返回结果列表
    result = []
    for m in qs:
        result.append({
            "user_id": m.user.user_id,
            "username": m.user.username,
            "device_id": m.device.device_id,
            "device_name": m.device.device_name,
            "permission": m.permission
        })

    # 返回总数和映射列表
    return api_response(
        data={"total": len(result), "mappings": result},
        message="查询成功",
        code=0,
        status=200
    )


def retrieve_mapping(request, user_id, device_id):
    """
    获取单条映射详情。
    Endpoint: GET /api/v1/user-device-map/<user_id>/<device_id>/
    当指定用户和设备的映射不存在时，自动返回 404。
    """
    if request.method != 'GET':
        return HttpResponseNotAllowed(permitted_methods=['GET'])

    # 使用 get_object_or_404 方便地处理不存在时报 404
    mapping = get_object_or_404(
        UserDeviceMap,
        user_id=user_id,
        device_id=device_id
    )
    data = {
        "user_id": mapping.user.user_id,
        "username": mapping.user.username,
        "device_id": mapping.device.device_id,
        "device_name": mapping.device.device_name,
        "permission": mapping.permission
    }
    return api_response(data=data, message="查询单条成功", code=0, status=200)


def update_mapping(request, user_id, device_id):
    """
    更新已有映射的权限字段。
    Endpoint: PUT /api/v1/user-device-map/<user_id>/<device_id>/
    Request Body (JSON): {"permission": "new_permission"}
    """
    if request.method != 'PUT':
        return HttpResponseNotAllowed(permitted_methods=['PUT'])

    # 解析并验证 JSON 请求体
    try:
        body = json.loads(request.body)
        new_permission = str(body.get('permission')).strip()
    except (json.JSONDecodeError, TypeError):
        return HttpResponseBadRequest(
            "请求体格式错误，必须是 JSON 且包含 permission 字段"
        )

    # 获取映射，若不存在自动返回 404
    mapping = get_object_or_404(
        UserDeviceMap,
        user_id=user_id,
        device_id=device_id
    )
    # 更新权限并保存
    mapping.permission = new_permission
    mapping.save()

    data = {
        "user_id": mapping.user_id,
        "device_id": mapping.device_id,
        "permission": mapping.permission
    }
    return api_response(data=data, message="更新成功", code=0, status=200)


def delete_mapping(request, user_id, device_id):
    """
    删除指定的用户-设备映射。
    Endpoint: DELETE /api/v1/user-device-map/<user_id>/<device_id>/
    """
    if request.method != 'DELETE':
        return HttpResponseNotAllowed(permitted_methods=['DELETE'])

    # 获取映射并删除，若不存在自动返回 404
    mapping = get_object_or_404(
        UserDeviceMap,
        user_id=user_id,
        device_id=device_id
    )
    mapping.delete()

    # 删除成功不返回 data
    return api_response(message="删除成功", code=0, status=200)
